/*
* File: config.cpp
* Version: 1.0
* Last modified on 2014-03-18 15:00
* Contributors : Nicklas Wallman (s131448), Olof Ivarsson(s132046), Oscar Ernstsson(s132952), Oscar Pehrson(s131469), Martin Jakobsson(s133082)
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "config.h"

/*
 * Constants:
 * ----------------
 */
#define CFG_FILENAME "config.txt"
#define CFG_LOG_FILENAME "logfile.txt"

#define CFG_HTTP_KEY			"httpPort"
#define CFG_TELNETPORT_KEY      "telnetPort"
#define CFG_WEBPATH_KEY			"webPath"
#define CFG_LOGPATH_KEY			"logPath"
#define CFG_TELNETPWD_KEY		"telnetPassword"


// Global variable that will be accessable from other modules using the extern keyword.
configT srvConfig;

/*
 * Function: getblock
 * Usage: memptr = getBlock(size)
 * --------------------------
 * This function allocates a block of memory, which depends on parameter size.
 */

static void *getBlock(size_t size);

/*
 * Function: initConfig
 * Usage: initConfig()
 * --------------------------
 * This function initializes the configuration, for instance, sets the variables httpPort and telnetPort to 0.
 */

static void initConfig(void);

/*
 * Function: parseCfgLine
 * Usage: parseCfgLine(cfgLine)
 * --------------------------
 * This function parses a configuration file. 
 *
 * The configuration file format is intended to be listed as key-value pairs, also known as hashes. 
 * For an example:
 *
 * httpPort = 80
 * telnetPort = 3030
 * webPath = C:\webroot
 * ..
 */

static void parseCfgLine(char *cfgLine);

/*
 * Function: getLine
 * Usage: line = getLine(filestream, &bytesRead)
 * --------------------------
 * This function reads a line from a file stream and returns a pointer to the string. It also modifies the variable "bytesRead" to how many bytes that were read during reading (simplifies looping, etc.). 
 */

static char *getLine(FILE *f, int *bytesRead);

/*
 * Function: removeSpaces
 * Usage: removeSpaces(str)
 * --------------------------
 * This function removes spaces from a string
 */
static char *removeSpaces(char* source);

/*
 * Function: createConfig
 * Usage: createConfig()
 * --------------------------
 * This function creates a config file and fills it with some default data.
 */

static void createConfig(void);

/*
 * Function: openConfig
 * Usage: file = openConfig()
 * --------------------------
 * This function checks if there's a config file. If so, it tries to open it and returns a FILE pointer.
 */

static FILE *openConfig(void);

static void initConfig(void)
{
	srvConfig.httpPort   = 8080;
	srvConfig.telnetPort = 8081;
}

static FILE *openConfig(void)
{
	FILE *f;

	if ( (f = fopen(CFG_FILENAME, "r")) != NULL)
	{
		return f;
	}
	return NULL;
}
static void createConfig(void)
{
	FILE *f;

	f = fopen(CFG_FILENAME, "w");
	if (f != NULL)
	{
		fprintf(f, "%s = 8080 \n%s = 8081\n%s = c:/webb\n%s = c:/webb/logs/%s\n%s = adminpass", CFG_HTTP_KEY, CFG_TELNETPORT_KEY, CFG_WEBPATH_KEY, CFG_LOGPATH_KEY,CFG_LOG_FILENAME, CFG_TELNETPWD_KEY);
		fclose(f);
	}
}
static void parseCfgLine(char *cfgLine)
{
	char *key, *val;

	if (strlen(cfgLine) < 1)
		return;

	cfgLine = removeSpaces(cfgLine);

	key = strtok(cfgLine, "=" );
	
	if (strcmp(key, CFG_HTTP_KEY) == 0)
	{
		val = strtok(NULL, "=");
		srvConfig.httpPort = atoi(val);

	} else if (strcmp(key, CFG_TELNETPORT_KEY) == 0)
	{
		val = strtok(NULL, "=");
		srvConfig.telnetPort = atoi(val);

	} else if (strcmp(key, CFG_TELNETPWD_KEY) == 0)
	{
		val = strtok(NULL, "=");
		strcpy(srvConfig.telnetPwd, val);
	} else if (strcmp(key, CFG_WEBPATH_KEY) == 0)
	{
		val = strtok(NULL, "=");
		strcpy(srvConfig.webPath, val);
	} else if (strcmp(key, CFG_LOGPATH_KEY) == 0)
	{
		val = strtok(NULL, "=");
		strcpy(srvConfig.logPath, val);
	}
}

void loadConfig(void)
{
	FILE *f;
	int ch, bytesRead;
	char *line, cfgLine[512];

	line = "";
	bytesRead = 0;
	initConfig();

	f = openConfig();
	if (f == NULL)
	{
		// Config file doesn't exist, let's try create it and open it again
		createConfig();
		f = openConfig();

		if (f == NULL)
		{
			fprintf(stderr, "Errors prevented configuration file from being loaded properly.");
			fclose(f);
		}
	}
	do
	{
		parseCfgLine(line);

	} while ( (line = getLine(f, &bytesRead)) != NULL && bytesRead > 0);
}

static void *getBlock(size_t size)
{
	void *memblock;

	memblock = malloc(size);
	return memblock;
}

static char *getLine(FILE *f, int *bytesRead)
{
	char *buf, *tmpbuf;
	int ch, currMemSize, n;

	n = 0;
	currMemSize = 100;
	buf = (char *) malloc(currMemSize);

	while ( (ch = fgetc(f)) != '\n' && ch != EOF )
	{
		buf[n] = (char)ch;
		n++;
		// we need more memory
		if (currMemSize == n)
		{
			tmpbuf = (char *)getBlock(currMemSize * 2 + 1);
			memcpy(tmpbuf, buf, currMemSize);
			currMemSize *= 2;
			free(buf);
			buf = tmpbuf;
		}
	}

	if (n == 0 && ch == EOF)
	{
		free(buf);
		return (NULL);
	}

	buf[n++] = '\0';
	*bytesRead = n;

	return buf;
}

static char *removeSpaces(char* source)
{
	
  int n, i;
  char *newstr;

  n = 0;
  newstr = (char*) malloc(strlen(source));
  memset(newstr, 0, strlen(source));


  for (i = 0; i < strlen(source); i++)
  {
	  if (!isspace(source[i]))
	  {
		  newstr[n] = source[i];
		  n++;
	  }
  }

  return newstr;
}